package com.ylr.blog.framework.manager;

import com.ylr.user.common.dto.user.UserDto;
import com.ylr.base.common.dto.NameValue;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.po.user.UserPo;
import com.ylr.base.common.utils.UserUtils;
import com.ylr.blog.common.constant.BlogConstant;
import com.ylr.blog.common.dto.audit_blog.AuditBlogDetailDto;
import com.ylr.blog.common.enums.AuditBlogFlowEnum;
import com.ylr.blog.common.enums.BlogEnum;
import com.ylr.blog.common.vo.audit_blog.AssignVo;
import com.ylr.blog.common.vo.audit_blog.AuditVo;
import com.ylr.blog.common.vo.blog.BlogVo;
import com.ylr.blog.framework.entity.AuditBlogEntity;
import com.ylr.blog.framework.entity.AuditBlogFlowEntity;
import com.ylr.blog.framework.entity.BlogEntity;
import com.ylr.blog.framework.service.*;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.infra.hint.HintManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-06-05 10:33:28
 * className: AuditBlogManager
 * version: 1.0
 * description:
 */
@Service("auditBlogManager")
@AllArgsConstructor
public class AuditBlogManager {

    private static final Logger log = LoggerFactory.getLogger(AuditBlogManager.class);

    private final AuditBlogService auditBlogService;

    private final AuditBlogFlowService auditBlogFlowService;

    private final BlogContentService blogContentService;

    private final BlogTagRelationService blogTagRelationService;

    private final BlogService blogService;

    /**
     * 保存待审核博客操作
     * @param blogVo 参数对象
     */
    @Transactional
    public void saveAuditBlog(BlogVo blogVo) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, blogVo.getCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, blogVo.getCode());
            // 博客正文表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_CONTENT, blogVo.getCode());
            hintManager.addTableShardingValue(BlogConstant.BLOG_CONTENT, blogVo.getCode());
            // 博客与博客标签关联表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_TAG_RELATION, blogVo.getCode());
            hintManager.addTableShardingValue(BlogConstant.BLOG_TAG_RELATION, blogVo.getCode());

            // 1、添加提交审核博客
            Long auditBlogId = auditBlogService.saveAuditBlog(blogVo);

            // 2、保存博客正文
            blogContentService.saveBlogContent(auditBlogId, blogVo.getContent());

            // 3、博客关联标签
            blogTagRelationService.saveBlogTagRelation(auditBlogId, blogVo.getTagIdList());
        }
    }

    /**
     * 保存待审核博客操作
     * @param blog 博客对象
     */
    @Transactional
    public void addAuditBlog(BlogEntity blog) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, blog.getCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, blog.getCode());
            // 博客正文表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_CONTENT, blog.getCode());
            hintManager.addTableShardingValue(BlogConstant.BLOG_CONTENT, blog.getCode());
            // 博客与博客标签关联表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_TAG_RELATION, blog.getCode());
            hintManager.addTableShardingValue(BlogConstant.BLOG_TAG_RELATION, blog.getCode());

            // 1、添加提交审核博客
            Long auditBlogId = auditBlogService.addAuditBlog(blog);

            // 2、保存博客正文
            String content = blogContentService.getContent(blog.getId());
            blogContentService.saveBlogContent(auditBlogId, content);

            // 3、博客关联标签
            blogTagRelationService.copyBlogTagRelation(blog.getId(), auditBlogId);
        }
    }

    /**
     * 获取待审核博客操作
     * @param id   主键
     * @param code 博客编号
     * @return 待审核博客对象
     */
    public AuditBlogDetailDto getAuditBlog(Long id, String code) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, code);
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, code);
            // 博客正文表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_CONTENT, code);
            hintManager.addTableShardingValue(BlogConstant.BLOG_CONTENT, code);
            // 博客与博客标签关联表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_TAG_RELATION, code);
            hintManager.addTableShardingValue(BlogConstant.BLOG_TAG_RELATION, code);

            // 1、获取待审核博客
            AuditBlogEntity auditBlog = auditBlogService.getAuditBlog(id);

            // 2、获取博客正文
            String content = blogContentService.getContent(id);

            // 3、获取博客关联的博客标签
            List<NameValue<String>> blogTagList = blogTagRelationService.getBlogTagList(id);

            // 数据封装
            AuditBlogDetailDto auditBlogDetailDto = new AuditBlogDetailDto();
            auditBlogDetailDto.setId(auditBlog.getId().toString())
                    .setBlogId(auditBlog.getBlogId().toString())
                    .setCode(auditBlog.getCode())
                    .setTitle(auditBlog.getTitle())
                    .setPreface(auditBlog.getPreface())
                    .setCoverPicture(auditBlog.getCoverPicture())
                    .setType(auditBlog.getType())
                    .setTypeName(Optional.ofNullable(auditBlog.getType()).map(BlogEnum::getTypeEnum).map(BlogEnum::getName).orElse(StringUtils.EMPTY))
                    .setStatus(auditBlog.getStatus())
                    .setStatusName(Optional.ofNullable(auditBlog.getStatus()).map(BlogEnum::getStatusEnum).map(BlogEnum::getName).orElse(StringUtils.EMPTY))
                    .setContent(Optional.ofNullable(content).orElse(StringUtils.EMPTY))
                    .setBlogTagList(blogTagList);
            return null;
        }
    }

    /**
     * 获取被分单用户操作
     * @param id 被分单用户主键
     * @return 被分单用户对象
     */
    public UserDto getAuditUser(Long id, String code) {
        try (HintManager hintManager = HintManager.getInstance()) {
            // 添加分库分表的分片键
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, code);
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, code);

            return auditBlogService.getAuditUser(id);
        }
    }

    /**
     * 博客审核分单操作
     * 分单、委托、复审、转派
     * @param assignVo 参数对象
     */
    @Transactional
    public void assignAudit(AssignVo assignVo) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, assignVo.getBlogCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, assignVo.getBlogCode());
            // 博客审核流水表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG_FLOW, assignVo.getBlogCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG_FLOW, assignVo.getBlogCode());

            // 1、修改待审核博客
            auditBlogService.assignAudit(assignVo);

            // 2、增加博客审核流水
            auditBlogFlowService.saveAuditBlogFlow(assignVo.getId(), assignVo.getAuditUser(), assignVo.getType(), Optional.ofNullable(assignVo.getRemark()).orElse(StringUtils.EMPTY));
        }
    }

    /**
     * 终止博客审核操作
     * @param code 博客编号
     * @param id   主键
     */
    public void stopAuditBlog(String code, Long id) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, code);
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, code);
            // 博客审核流水表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG_FLOW, code);
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG_FLOW, code);

            // 1、终止博客审核
            auditBlogService.stopAuditBlog(id);

            // 2、添加博客审核流水
            auditBlogFlowService.saveAuditBlogFlow(id, CommonEnum.DEFAULT_ID.getLongValue(),
                    AuditBlogFlowEnum.WITHDRAW.getValue(), StringUtils.EMPTY);
        }
    }

    /**
     * 提交博客审核结果操作
     * @param auditVo 参数对象
     */
    @Transactional
    public void commitAudit(AuditVo auditVo) {
        try (HintManager hintManager = HintManager.getInstance()) {
            /*
                添加分库分表的分片键
             */
            // 提交审核博客表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG, auditVo.getBlogCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG, auditVo.getBlogCode());
            // 博客审核流水表
            hintManager.addDatabaseShardingValue(BlogConstant.AUDIT_BLOG_FLOW, auditVo.getBlogCode());
            hintManager.addTableShardingValue(BlogConstant.AUDIT_BLOG_FLOW, auditVo.getBlogCode());
            // 博客状态流水表
            hintManager.addDatabaseShardingValue(BlogConstant.BLOG_FLOW, auditVo.getBlogCode());
            hintManager.addTableShardingValue(BlogConstant.BLOG_FLOW, auditVo.getBlogCode());


            // 获取正在提交博客审核的用户
            UserPo userPo = UserUtils.getUser();

            // 1、更新待审核博客
            auditBlogService.commitAudit(auditVo);

            // 获取最新一条博客审核流水
            AuditBlogFlowEntity auditBlogFlow = auditBlogFlowService.getLastOne(auditVo.getId());
            if (Objects.isNull(auditBlogFlow)) {
                log.error("博客审核流水丢失");
                throw new YlrException();
            }
            Integer type = AuditBlogFlowEnum.CHECK_PASS.getValue();
            Integer status = BlogEnum.AUDIT_PASS.getValue();
            if (AuditBlogFlowEnum.RECHECK.getValue().equals(auditBlogFlow.getType())) {
                type = AuditBlogFlowEnum.RECHECK_PASS.getValue();
                status = BlogEnum.RECHECK_PASS.getValue();
            }
            if (auditVo.isAuditReject()) {
                type = AuditBlogFlowEnum.CHECK_REJECT.getValue();
                status = BlogEnum.AUDIT_REJECT.getValue();

                if (AuditBlogFlowEnum.RECHECK.getValue().equals(auditBlogFlow.getType())) {
                    type = AuditBlogFlowEnum.RECHECK_REJECT.getValue();
                    status = BlogEnum.RECHECK_REJECT.getValue();
                }
            }

            // 2、增加审核流水
            auditBlogFlowService.saveAuditBlogFlow(auditVo.getId(), userPo.getId(), type, StringUtils.EMPTY);

            // 3、更新博客
            blogService.updateBlogStatus(auditVo.getBlogId(), auditVo.getBlogCode(), status);
        }



    }

}
